package com.fm.service;

/**
 * Created by Administrator on 2018/7/30 0030.
 */

import com.fm.entity.Product;
import com.fm.entity.ProductFunction;
import com.fm.mapper.ProductMapper;
import com.fm.objectModal.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ProductService extends MBaseService<Product, Integer, ProductMapper>{

    @Autowired
    private ProductFunctionService productFunctionService;



    public Product getProductByKey(String key) {
        Product product = new Product();
        product.setProductKey(key);
        return getMyBatisDao().findOne(Example.of(product)).get();
    }

    /**
     * 根据产品生成物模型
     * @param productId
     * @return
     */
    public ObjectModal formatObjectModal(Integer productId) {
        ObjectModal modal = new ObjectModal();
        Product product = getMyBatisDao().getOne(productId);
        modal.setSchema("https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json");
        Profile profile = new Profile();
        //属性
        List<Property> properties = new ArrayList<>();
        //服务
        List<com.fm.objectModal.Service> services = new ArrayList<>();
        //事件
        List<Event> events = new ArrayList<>();

        profile.setProductKey(product.getProductKey());
//        profile.setDeviceName(product.getName());

        //下面是属性、事件和方法
        ProductFunction entity = new ProductFunction();
        entity.setParentId(0);
        entity.setProductId(productId);
        List<ProductFunction> propertyList = productFunctionService.selectByExample(entity);
        for (ProductFunction function : propertyList) {
            if (function.getType() == 1) {//属性
                properties.add(getProperty(function));
            }else if (function.getType() == 2) {//服务
                services.add(getService(function));
            }else if (function.getType() == 3){
                events.add(getEvent(function));
            }
        }
        //添加通用的服务和事件
        services.addAll(getParamSetService(properties));
        events.add(getParamEvent(properties));

        modal.setProfile(profile);
        modal.setProperties(properties);
        modal.setServices(services);
        modal.setEvents(events);
        return modal;
    }

    //获取一个属性
    private Property getProperty(ProductFunction property) {
        Property p = new Property();
        p.setName(property.getName());
        p.setAccessMode(property.getWrAuth()==1?"rw":"r");
        p.setIdentifier(property.getIdentifier());
        p.setDesc(property.getIntroduce());
        p.setRequired(true);
        p.setDataType(getType(property));
        return p;
    }

    /**
     * 获取服务
     * @param service
     * @return
     */
    private com.fm.objectModal.Service getService(ProductFunction service) {
        com.fm.objectModal.Service s = new com.fm.objectModal.Service();
        s.setName(service.getName());
        s.setDesc(service.getIntroduce());
        s.setIdentifier(service.getIdentifier());
        s.setCallType(service.getMethodType()==1?"async":"sync");
        s.setRequired(true);
        s.setMethod("thing.service."+service.getIdentifier());
        //获取参数
        ProductFunction entity = new ProductFunction();
        entity.setProductId(service.getProductId());
        entity.setParentId(service.getId());
        List<ProductFunction> propertyList = productFunctionService.selectByExample(entity);
        List<Property> out = new ArrayList<>();
        List<Property> input = new ArrayList<>();
        for (ProductFunction function : propertyList) {
            Property property = getProperty(function);
            if (function.getType() == 4) input.add(property);
            else if (function.getType() == 5) out.add(property);
        }
        s.setInputData(input);
        s.setOutputData(out);
        return s;
    }

    /**
     * 获取事件
     * @param event
     * @return
     */
    private Event getEvent(ProductFunction event) {
        Event e = new Event();
        e.setName(event.getName());
        if (event.getFunctionType() == 1) e.setType("info");
        else if (event.getFunctionType() == 2) e.setType("alert");
        else if (event.getFunctionType() == 3) e.setType("error");
        e.setDesc(event.getIntroduce());
        e.setIdentifier(event.getIdentifier());
        e.setRequired(true);
        e.setMethod("thing.event."+event.getIdentifier()+".post");
        //获取参数
        ProductFunction entity = new ProductFunction();
        entity.setProductId(event.getProductId());
        entity.setParentId(event.getId());
        List<ProductFunction> propertyList = productFunctionService.selectByExample(entity);
        List<Property> out = new ArrayList<>();
        for (ProductFunction function : propertyList) {
            Property property = getProperty(function);
            out.add(property);
        }
        e.setOutputData(out);
        return e;
    }

    private DataType getType(ProductFunction function) {
        DataType dataType = new DataType();
        switch (function.getDataFormat()){
            case 1:
                dataType.setType("int");
                dataType.setSpecs(getNumberDes(function));
                break;
            case 2:
                dataType.setType("float");
                dataType.setSpecs(getNumberDes(function));
                break;
            case 3:
                dataType.setType("double");
                dataType.setSpecs(getNumberDes(function));
                break;
            case 4:
                dataType.setType("text");
                dataType.setSpecs(getTextDes(function));
                break;
            case 5:
                dataType.setType("date");
                dataType.setSpecs(new HashMap<>());
                break;
            case 6:
                dataType.setType("bool");
                dataType.setSpecs(getBooleanDes(function));
                break;
            case 7:
                dataType.setType("enum");
                dataType.setSpecs(getEnumDes(function));
                break;
            case 8:
                dataType.setType("array");
                dataType.setSpecs(getArrayDes(function));
                break;
            default:
                break;
        }
        return dataType;
    }

    private Map<String, Object> getNumberDes(ProductFunction function){
        Map<String, Object> des = new HashMap<>();
        des.put("min", function.getMin()+"");
        des.put("max", function.getMax()+"");
        des.put("step", function.getResolutionRatio()+"");
        des.put("unit", getUnit(function.getUnit()));
        return des;
    }
    private Map<String, Object> getTextDes(ProductFunction function){
        Map<String, Object> des = new HashMap<>();
        des.put("length", function.getTextLength()+"");
        return des;
    }
    private Map<String, Object> getBooleanDes(ProductFunction function){
        String boolvalue [] = function.getBoolValue().split(",");
        Map<String, Object> des = new HashMap<>();
        des.put("0", boolvalue[0]);
        des.put("1", boolvalue[1]);
        return des;
    }
    private Map<String, Object> getEnumDes(ProductFunction function){
        String enumValues [] = function.getEnumItems().split(",");
        Map<String, Object> des = new HashMap<>();
        for (String enumval : enumValues) {
            String ens []= enumval.split(":");
            des.put(ens[0], ens[1]);
        }
        return des;
    }
    private Map<String, Object> getArrayDes(ProductFunction function){
        Map<String, Object> des = new HashMap<>();
        des.put("size", "128");
        Map<String, String> item = new HashMap<>();
        item.put("type", function.getArrayType()+"");
        des.put("item", item);
        return des;
    }
    /**
     * 获取单位
     * @param unit
     * @return
     */
    private String getUnit(Integer unit) {
        switch (unit){
            case 1:
                return "int";
            case 2:
                return "float";
            case 3:
                return "double";
            case 4:
                return "text";
            case 5:
                return "date";
            case 6:
                return "bool";
            case 7:
                return "enum";
            case 8:
                return "array";
            default:
                return "";
        }
    }

    private List<com.fm.objectModal.Service> getParamSetService(List<Property> params) {
        List<com.fm.objectModal.Service> services = new ArrayList<>();
        com.fm.objectModal.Service set = new com.fm.objectModal.Service();
        set.setName("set");
        set.setDesc("属性设置");
        set.setIdentifier("set");
        set.setCallType("async");
        set.setRequired(true);
        set.setMethod("thing.service.property.set");
        set.setInputData(params);
        services.add(set);
        com.fm.objectModal.Service get = new com.fm.objectModal.Service();
        get.setName("get");
        get.setDesc("属性获取");
        get.setIdentifier("get");
        get.setCallType("async");
        get.setRequired(true);
        get.setMethod("thing.service.property.get");
        get.setOutputData(params);
        services.add(get);
        return services;
    }

    private Event getParamEvent(List<Property> params) {
        Event event = new Event();
        event.setName("post");
        event.setDesc("属性上报");
        event.setIdentifier("post");
        event.setMethod("thing.event.property.post");
        event.setType("info");
        event.setRequired(true);
        event.setOutputData(params);

        return event;
    }
}
